package cool.mtc.web.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import cool.mtc.core.util.CollectionUtil;
import cool.mtc.web.WebProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;
import java.util.Optional;

/**
 * @author 明河
 */
@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WebConfigurer implements WebMvcConfigurer {
    private final WebProperties webProperties;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations(webProperties.getPath());
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("forward:/index.html");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }

    /**
     * 跨域配置
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        if (CollectionUtil.isEmpty(webProperties.getCors())) {
            return;
        }
        for (WebProperties.Cors cors : webProperties.getCors()) {
            if (!cors.isEnabled()) {
                continue;
            }
            CorsRegistration corsRegistration = registry.addMapping(cors.getPathPattern()).allowCredentials(true);
            Optional.ofNullable(cors.getAllowedOrigins()).ifPresent(corsRegistration::allowedOrigins);
            Optional.ofNullable(cors.getAllowedOriginPatterns()).ifPresent(corsRegistration::allowedOriginPatterns);
            Optional.ofNullable(cors.getAllowedMethods()).ifPresent(corsRegistration::allowedMethods);
            Optional.ofNullable(cors.getAllowedHeaders()).ifPresent(corsRegistration::allowedHeaders);
            Optional.ofNullable(cors.getExposedHeaders()).ifPresent(corsRegistration::exposedHeaders);
        }
    }

    /**
     * Long转为String返回，防止前端使用number类型损失精度
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = new ObjectMapper();

        for (HttpMessageConverter<?> item : converters) {
            if (item instanceof MappingJackson2HttpMessageConverter) {
                mapper = ((MappingJackson2HttpMessageConverter) item).getObjectMapper();
                break;
            }
        }

        SimpleModule module = new SimpleModule();
        module.addSerializer(Long.class, ToStringSerializer.instance);
        module.addSerializer(Long.TYPE, ToStringSerializer.instance);
        mapper.registerModule(module);

        converter.setObjectMapper(mapper);
        converters.add(0, converter);
    }

}
